1   /*
2    * Copyright (C) 2007 The Guava Authors
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package com.google.common.collect;
18  
19  import static com.google.common.truth.Truth.assertThat;
20  
21  import com.google.common.annotations.GwtCompatible;
22  import com.google.common.collect.testing.DerivedComparable;
23  
24  import junit.framework.TestCase;
25  
26  import java.util.Arrays;
27  import java.util.Collections;
28  import java.util.List;
29  
30  /**
31   * Tests for {@link Multisets}.
32   *
33   * @author Mike Bostock
34   * @author Jared Levy
35   * @author Louis Wasserman
36   */
37  @GwtCompatible(emulated = true)
38  public class MultisetsTest extends TestCase {
39  
40    /* See MultisetsImmutableEntryTest for immutableEntry() tests. */
41  
42    public void testNewTreeMultisetDerived() {
43      TreeMultiset<DerivedComparable> set = TreeMultiset.create();
44      assertTrue(set.isEmpty());
45      set.add(new DerivedComparable("foo"), 2);
46      set.add(new DerivedComparable("bar"), 3);
47      assertThat(set).has().exactly(
48          new DerivedComparable("bar"), new DerivedComparable("bar"), new DerivedComparable("bar"),
49          new DerivedComparable("foo"), new DerivedComparable("foo")).inOrder();
50    }
51  
52    public void testNewTreeMultisetNonGeneric() {
53      TreeMultiset<LegacyComparable> set = TreeMultiset.create();
54      assertTrue(set.isEmpty());
55      set.add(new LegacyComparable("foo"), 2);
56      set.add(new LegacyComparable("bar"), 3);
57      assertThat(set).has().exactly(new LegacyComparable("bar"),
58          new LegacyComparable("bar"), new LegacyComparable("bar"),
59          new LegacyComparable("foo"), new LegacyComparable("foo")).inOrder();
60    }
61  
62    public void testNewTreeMultisetComparator() {
63      TreeMultiset<String> multiset
64          = TreeMultiset.create(Collections.reverseOrder());
65      multiset.add("bar", 3);
66      multiset.add("foo", 2);
67      assertThat(multiset).has().exactly("foo", "foo", "bar", "bar", "bar").inOrder();
68    }
69  
70    public void testRetainOccurrencesEmpty() {
71      Multiset<String> multiset = HashMultiset.create();
72      Multiset<String> toRetain =
73          HashMultiset.create(Arrays.asList("a", "b", "a"));
74      assertFalse(Multisets.retainOccurrences(multiset, toRetain));
75      assertThat(multiset).isEmpty();
76    }
77  
78    public void testRemoveOccurrencesIterableEmpty() {
79      Multiset<String> multiset = HashMultiset.create();
80      Iterable<String> toRemove = Arrays.asList("a", "b", "a");
81      assertFalse(Multisets.removeOccurrences(multiset, toRemove));
82      assertTrue(multiset.isEmpty());
83    }
84  
85    public void testRemoveOccurrencesMultisetEmpty() {
86      Multiset<String> multiset = HashMultiset.create();
87      Multiset<String> toRemove =
88          HashMultiset.create(Arrays.asList("a", "b", "a"));
89      assertFalse(Multisets.retainOccurrences(multiset, toRemove));
90      assertTrue(multiset.isEmpty());
91    }
92  
93    public void testUnion() {
94      Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
95      Multiset<String> ms2 = HashMultiset.create(
96          Arrays.asList("a", "b", "b", "c"));
97      assertThat(Multisets.union(ms1, ms2)).has().exactly("a", "a", "b", "b", "c");
98    }
99  
100   public void testUnionEqualMultisets() {
101     Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
102     Multiset<String> ms2 = HashMultiset.create(Arrays.asList("a", "b", "a"));
103     assertEquals(ms1, Multisets.union(ms1, ms2));
104   }
105 
106   public void testUnionEmptyNonempty() {
107     Multiset<String> ms1 = HashMultiset.create();
108     Multiset<String> ms2 = HashMultiset.create(Arrays.asList("a", "b", "a"));
109     assertEquals(ms2, Multisets.union(ms1, ms2));
110   }
111 
112   public void testUnionNonemptyEmpty() {
113     Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
114     Multiset<String> ms2 = HashMultiset.create();
115     assertEquals(ms1, Multisets.union(ms1, ms2));
116   }
117 
118   public void testIntersectEmptyNonempty() {
119     Multiset<String> ms1 = HashMultiset.create();
120     Multiset<String> ms2 = HashMultiset.create(Arrays.asList("a", "b", "a"));
121     assertThat(Multisets.intersection(ms1, ms2)).isEmpty();
122   }
123 
124   public void testIntersectNonemptyEmpty() {
125     Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
126     Multiset<String> ms2 = HashMultiset.create();
127     assertThat(Multisets.intersection(ms1, ms2)).isEmpty();
128   }
129 
130   public void testSum() {
131     Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
132     Multiset<String> ms2 = HashMultiset.create(Arrays.asList("b", "c"));
133     assertThat(Multisets.sum(ms1, ms2)).has().exactly("a", "a", "b", "b", "c");
134   }
135 
136   public void testSumEmptyNonempty() {
137     Multiset<String> ms1 = HashMultiset.create();
138     Multiset<String> ms2 = HashMultiset.create(Arrays.asList("a", "b", "a"));
139     assertThat(Multisets.sum(ms1, ms2)).has().exactly("a", "b", "a");
140   }
141 
142   public void testSumNonemptyEmpty() {
143     Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
144     Multiset<String> ms2 = HashMultiset.create();
145     assertThat(Multisets.sum(ms1, ms2)).has().exactly("a", "b", "a");
146   }
147 
148   public void testDifferenceWithNoRemovedElements() {
149     Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
150     Multiset<String> ms2 = HashMultiset.create(Arrays.asList("a"));
151     assertThat(Multisets.difference(ms1, ms2)).has().exactly("a", "b");
152   }
153 
154   public void testDifferenceWithRemovedElement() {
155     Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
156     Multiset<String> ms2 = HashMultiset.create(Arrays.asList("b"));
157     assertThat(Multisets.difference(ms1, ms2)).has().exactly("a", "a");
158   }
159 
160   public void testDifferenceWithMoreElementsInSecondMultiset() {
161     Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
162     Multiset<String> ms2 = HashMultiset.create(Arrays.asList("a", "b", "b", "b"));
163     Multiset<String> diff = Multisets.difference(ms1, ms2);
164     assertThat(diff).has().item("a");
165     assertEquals(0, diff.count("b"));
166     assertEquals(1, diff.count("a"));
167     assertFalse(diff.contains("b"));
168     assertTrue(diff.contains("a"));
169   }
170 
171   public void testDifferenceEmptyNonempty() {
172     Multiset<String> ms1 = HashMultiset.create();
173     Multiset<String> ms2 = HashMultiset.create(Arrays.asList("a", "b", "a"));
174     assertEquals(ms1, Multisets.difference(ms1, ms2));
175   }
176 
177   public void testDifferenceNonemptyEmpty() {
178     Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
179     Multiset<String> ms2 = HashMultiset.create();
180     assertEquals(ms1, Multisets.difference(ms1, ms2));
181   }
182 
183   public void testContainsOccurrencesEmpty() {
184     Multiset<String> superMultiset = HashMultiset.create(Arrays.asList("a", "b", "a"));
185     Multiset<String> subMultiset = HashMultiset.create();
186     assertTrue(Multisets.containsOccurrences(superMultiset, subMultiset));
187     assertFalse(Multisets.containsOccurrences(subMultiset, superMultiset));
188   }
189 
190   public void testContainsOccurrences() {
191     Multiset<String> superMultiset = HashMultiset.create(Arrays.asList("a", "b", "a"));
192     Multiset<String> subMultiset = HashMultiset.create(Arrays.asList("a", "b"));
193     assertTrue(Multisets.containsOccurrences(superMultiset, subMultiset));
194     assertFalse(Multisets.containsOccurrences(subMultiset, superMultiset));
195     Multiset<String> diffMultiset = HashMultiset.create(Arrays.asList("a", "b", "c"));
196     assertFalse(Multisets.containsOccurrences(superMultiset, diffMultiset));
197     assertTrue(Multisets.containsOccurrences(diffMultiset, subMultiset));
198   }
199 
200   public void testRetainEmptyOccurrences() {
201     Multiset<String> multiset =
202         HashMultiset.create(Arrays.asList("a", "b", "a"));
203     Multiset<String> toRetain = HashMultiset.create();
204     assertTrue(Multisets.retainOccurrences(multiset, toRetain));
205     assertTrue(multiset.isEmpty());
206   }
207 
208   public void testRetainOccurrences() {
209     Multiset<String> multiset =
210         TreeMultiset.create(Arrays.asList("a", "b", "a", "c"));
211     Multiset<String> toRetain =
212         HashMultiset.create(Arrays.asList("a", "b", "b"));
213     assertTrue(Multisets.retainOccurrences(multiset, toRetain));
214     assertThat(multiset).has().exactly("a", "b").inOrder();
215   }
216 
217   public void testRemoveEmptyOccurrencesMultiset() {
218     Multiset<String> multiset =
219         TreeMultiset.create(Arrays.asList("a", "b", "a"));
220     Multiset<String> toRemove = HashMultiset.create();
221     assertFalse(Multisets.removeOccurrences(multiset, toRemove));
222     assertThat(multiset).has().exactly("a", "a", "b").inOrder();
223   }
224 
225   public void testRemoveOccurrencesMultiset() {
226     Multiset<String> multiset =
227         TreeMultiset.create(Arrays.asList("a", "b", "a", "c"));
228     Multiset<String> toRemove =
229         HashMultiset.create(Arrays.asList("a", "b", "b"));
230     assertTrue(Multisets.removeOccurrences(multiset, toRemove));
231     assertThat(multiset).has().exactly("a", "c").inOrder();
232   }
233 
234   public void testRemoveEmptyOccurrencesIterable() {
235     Multiset<String> multiset =
236         TreeMultiset.create(Arrays.asList("a", "b", "a"));
237     Iterable<String> toRemove = ImmutableList.of();
238     assertFalse(Multisets.removeOccurrences(multiset, toRemove));
239     assertThat(multiset).has().exactly("a", "a", "b").inOrder();
240   }
241 
242   public void testRemoveOccurrencesMultisetIterable() {
243     Multiset<String> multiset =
244         TreeMultiset.create(Arrays.asList("a", "b", "a", "c"));
245     List<String> toRemove = Arrays.asList("a", "b", "b");
246     assertTrue(Multisets.removeOccurrences(multiset, toRemove));
247     assertThat(multiset).has().exactly("a", "c").inOrder();
248   }
249 
250   @SuppressWarnings("deprecation")
251   public void testUnmodifiableMultisetShortCircuit() {
252     Multiset<String> mod = HashMultiset.create();
253     Multiset<String> unmod = Multisets.unmodifiableMultiset(mod);
254     assertNotSame(mod, unmod);
255     assertSame(unmod, Multisets.unmodifiableMultiset(unmod));
256     ImmutableMultiset<String> immutable = ImmutableMultiset.of("a", "a", "b", "a");
257     assertSame(immutable, Multisets.unmodifiableMultiset(immutable));
258     assertSame(immutable, Multisets.unmodifiableMultiset((Multiset<String>) immutable));
259   }
260 
261   public void testHighestCountFirst() {
262     Multiset<String> multiset = HashMultiset.create(
263         Arrays.asList("a", "a", "a", "b", "c", "c"));
264     ImmutableMultiset<String> sortedMultiset =
265         Multisets.copyHighestCountFirst(multiset);
266 
267     assertThat(sortedMultiset.entrySet()).has().exactly(
268         Multisets.immutableEntry("a", 3), Multisets.immutableEntry("c", 2),
269         Multisets.immutableEntry("b", 1)).inOrder();
270 
271     assertThat(sortedMultiset).has().exactly(
272         "a",
273         "a",
274         "a",
275         "c",
276         "c",
277         "b").inOrder();
278 
279     assertThat(Multisets.copyHighestCountFirst(ImmutableMultiset.of())).isEmpty();
280   }
281 }
282